Introduction
Macau has undergone significant land reclamation over the last few
decades. Due to urban growth and limited original land area, reclamation
has played a dominant role in shaping the city’s modern landscape. This
study utilizes Landsat imagery to visualize and quantify land expansion
from 1990 to 2025, examining the temporal evolution of Macau’s land
extent.
本研究運用 Landsat 影像呈現並分析澳門過去三十多年來的土地擴張。
Data
The macau_geojson
was downloaded from the Map of Macau and GIS
data — download OSM vector layers and used as the spatial boundary
for cropping the Landsat imagery. This polygon boundary is used to crop
each Landsat scene to the study area.
macau_polygon <- st_read("https://geo2day.com/asia/china/macau.geojson")
## Reading layer `macau' from data source
## `https://geo2day.com/asia/china/macau.geojson' using driver `GeoJSON'
## Simple feature collection with 1 feature and 1 field
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 113.524 ymin: 22.073 xmax: 113.634 ymax: 22.221
## Geodetic CRS: WGS 84
plot(macau_polygon)

Landsat imagery from 1990-2025
The analysis uses multi-temporal Landsat imagery from 1990-2025,
downloaded from the United States Geological Survey(USGS) EarthExplorer Platfrom. The
Landsat data of each year contains multiple single band tif
files. These bands must be stacked into a multi-band raster before
visualization or analysis. For more detail information about Landsat
spectral bands, refer to Spectral Bands and Applications - NASA
Science.
Landsat4_19901224
Landsat4
landsat4_19901224 <- stack(
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B1.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B2.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B3.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B4.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B5.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_ST_B6.TIF",
"LT04_L2SP_122045_19901224_20200915_02_T1/LT04_L2SP_122045_19901224_20200915_02_T1_SR_B7.TIF"
)
names(landsat4_19901224) <- c("blue", "green", "red", "NIR", "SWIR","Thermal", "Mid-Infrared-IR") #rename bands
# plotRGB(landsat4_19901224, r=3, g = 2, b = 1, stretch = "lin")
summary(landsat4_19901224)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.19% of all cells)
## blue green red NIR SWIR Thermal Mid.Infrared.IR
## Min. 7765 6810 7769 7631 7308 34005 6726
## 1st Qu. 9853 9894 9023 8358 7887 41497 7712
## Median 10290 10885 10167 10067 9370 42118 8670
## 3rd Qu. 11574 12136 12347 15820 15353 42355 12981
## Max. 65535 65535 65535 65535 65535 48143 43193
## NA's 15652119 15652119 15652119 15652119 15652119 16295241 15652119
Landsat5_1995
Landsat5
landsat5_19951230 <- stack(
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B1.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B2.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B3.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B4.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B5.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_ST_B6.TIF",
"LT05_L2SP_122045_19951230_20200911_02_T1/LT05_L2SP_122045_19951230_20200911_02_T1_SR_B7.TIF"
)
names(landsat5_19951230) <- c("blue", "green", "red", "NIR", "SWIR", "Thermal", "Mid-Infrared") #rename bands
summary(landsat5_19951230)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.19% of all cells)
## blue green red NIR SWIR Thermal Mid.Infrared
## Min. 7298 7378 7323 7601 6851 20833 6775
## 1st Qu. 9396 9008 8356 8033 7455 41165 7360
## Median 9794 9519 8674 8180 7574 41898 7555
## 3rd Qu. 10144 10492 9704 9224 7852 42204 7760
## Max. 65535 32576 34031 36160 39083 48386 55567
## NA's 16170679 16170679 16170679 16170679 16170679 16839792 16170679
#crs(landsat5_19951230)
Landsat5_2000
Landsat5_20000906 <- stack(
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B1.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B2.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B3.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B4.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B5.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_ST_B6.TIF",
"LT05_L2SP_122045_20000906_20200906_02_T1/LT05_L2SP_122045_20000906_20200906_02_T1_SR_B7.TIF"
)
names(Landsat5_20000906) <- c("blue", "green", "red", "NIR", "SWIR", "Thermal", "Mid-Infrared") #rename bands
summary(Landsat5_20000906)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.18% of all cells)
## blue green red NIR SWIR Thermal Mid.Infrared
## Min. 6553 7301 7071 5673 7101 293 7102
## 1st Qu. 9165 9288 8869 8669 8179 42224 8092
## Median 10009 10461 9769 9635 8756 44346 8504
## 3rd Qu. 12701 12956 12345 17967 14075 44960 10993
## Max. 65535 65535 65535 65535 65535 53920 33750
## NA's 16272093 16272093 16272093 16272093 16272093 16993723 16272093
Landsat5_2005
Landsat7 can
not use
Landsat5_20051022 <- stack(
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B1.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B2.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B3.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B4.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B5.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_ST_B6.TIF",
"LT05_L2SP_122045_20051022_20200901_02_T1/LT05_L2SP_122045_20051022_20200901_02_T1_SR_B7.TIF"
)
names(Landsat5_20051022) <- c("blue", "green", "red", "NIR", "SWIR", "Thermal", "Mid-Infrared") #rename bands
summary(Landsat5_20051022)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.19% of all cells)
## blue green red NIR SWIR Thermal
## Min. 21 2766.0 4438.0 5986.0 6602 293
## 1st Qu. 9971 9731.0 8869.0 8371.0 7879 44359
## Median 10456 10462.0 9228.0 8633.0 8068 44445
## 3rd Qu. 10870 11229.5 10302.5 12128.5 9532 44596
## Max. 65535 65535.0 65535.0 65535.0 65535 53023
## NA's 15746497 15743798.0 15743798.0 15743798.0 15743798 16445022
## Mid.Infrared
## Min. 7072
## 1st Qu. 7707
## Median 7965
## 3rd Qu. 8590
## Max. 34869
## NA's 15743798
Landsat5_2010
Landsat5_20100326 <- stack(
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B1.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B2.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B3.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B4.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B5.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_ST_B6.TIF",
"LT05_L2SP_122045_20100326_20200824_02_T1/LT05_L2SP_122045_20100326_20200824_02_T1_SR_B7.TIF"
)
names(Landsat5_20100326) <- c("blue", "green", "red", "NIR", "SWIR", "Thermal", "Mid-Infrared") #rename bands
summary(Landsat5_20100326)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.18% of all cells)
## blue green red NIR SWIR Thermal Mid.Infrared
## Min. 4294 5635 6431 9438 8205 293 7726
## 1st Qu. 11465 11829 11233 12816 10840 38473 9447
## Median 15848 16399 16012 16787 16659 39337 15381
## 3rd Qu. 65535 25400 26028 26517 26035 42543 21860
## Max. 65535 36842 65535 65535 65535 51609 29990
## NA's 15828280 15828280 15828280 15828280 15828280 16529646 15828280
Landsat8_2015
Landsat8
Landsat8_20151018 <- stack(
#"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B1.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B2.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B3.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B4.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B5.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B6.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_SR_B7.TIF",
"LC08_L2SP_122045_20151018_20200908_02_T1/LC08_L2SP_122045_20151018_20200908_02_T1_ST_B10.TIF"
)
names(Landsat8_20151018) <- c( "blue", "green", "red", "NIR", "SWIR", "SWIR2",
"TIRS1") #rename bands
#Thermal Infrared Sensor (TIRS): Band 10 TIRS 1 (10.6 - 11.19 µm) 100 m
#"Coastal" = Band 1
summary(Landsat8_20151018)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.17% of all cells)
## blue green red NIR SWIR SWIR2 TIRS1
## Min. 8 501 1286.0 4396.00 7024 7224 1779
## 1st Qu. 7545 8046 7265.0 7196.00 7673 7651 42893
## Median 8033 8846 7679.5 7448.00 8123 8066 43954
## 3rd Qu. 8676 9872 9080.0 14610.25 11799 9555 44210
## Max. 51479 50344 51124.0 50987.00 38314 32640 51574
## NA's 17670117 17560794 17560794.0 17560794.00 17560794 17560794 18268483
Landsat8_2020
Landsat8_20201202 <- stack(
#"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B1.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B2.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B3.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B4.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B5.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B6.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_SR_B7.TIF",
"LC08_L2SP_122045_20201202_20210312_02_T1/LC08_L2SP_122045_20201202_20210312_02_T1_ST_B10.TIF"
)
names(Landsat8_20201202) <- c( "blue", "green", "red", "NIR", "SWIR", "SWIR2",
"TIRS1") #rename bands
#Thermal Infrared Sensor (TIRS): Band 10 TIRS 1 (10.6 - 11.19 µm) 100 m
summary(Landsat8_20201202)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.17% of all cells)
## blue green red NIR SWIR SWIR2 TIRS1
## Min. 19 3 1 2506 6872 7343 37954
## 1st Qu. 8002 8370 7301 7103 7529 7552 42471
## Median 8375 9058 7825 7254 7683 7684 42814
## 3rd Qu. 8872 10112 9413 13277 11250 9331 43142
## Max. 50082 49196 50005 50132 43358 42402 47476
## NA's 18474916 17866083 17720707 17564865 17564865 17564865 18274879
Landsat8_20250327
Landsat8_20250327 <- stack(
#"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B1.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B2.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B3.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B4.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B5.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B6.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_SR_B7.TIF",
"LC08_L2SP_122045_20250319_20250327_02_T1/LC08_L2SP_122045_20250319_20250327_02_T1_ST_B10.TIF"
)
names(Landsat8_20250327) <- c( "blue", "green", "red", "NIR", "SWIR", "SWIR2",
"TIRS1") #rename bands
summary(Landsat8_20250327)
## Warning in .local(object, ...): summary is an estimate based on a sample of 1e+05 cells (0.17% of all cells)
## blue green red NIR SWIR SWIR2 TIRS1
## Min. 3 2296 2858 4790.0 7322 7422.00 37104
## 1st Qu. 7646 8135 7336 7233.0 7838 7825.00 41830
## Median 8084 8817 7553 7511.0 8060 8022.00 42440
## 3rd Qu. 8794 9902 9066 11305.5 10092 8905.25 42905
## Max. 30960 31221 32198 33644.0 35120 33106.00 48329
## NA's 17428941 17428941 17428941 17428941.0 17428941 17428941.00 18153114
Crop
This section use macau boundary polygon to crop the study area from
each year Landsat stacked image.
macau_poly_utm <- st_transform(macau_polygon, crs = crs(Landsat5_20051022))
# match the projection
crop_1990 <- crop(landsat4_19901224, macau_poly_utm)
crop_1995 <- crop(landsat5_19951230, macau_poly_utm)
crop_2000 <- crop(Landsat5_20000906, macau_poly_utm)
crop_2005 <- crop(Landsat5_20051022, macau_poly_utm)
crop_2010 <- crop(Landsat5_20100326, macau_poly_utm)
crop_2015 <- crop(Landsat8_20151018, macau_poly_utm)
crop_2020 <- crop(Landsat8_20201202, macau_poly_utm)
crop_2025 <- crop(Landsat8_20250327, macau_poly_utm)
Visualization
True color composites were generated for each year using band
combinations (e.g., R = Red, G = Green, B = Blue).
landsat_image_mo_list <- list(crop_1990, crop_1995, crop_2000, crop_2005, crop_2010,
crop_2015, crop_2020, crop_2025)
layer_date <- c("1990-12-24", "1995-12-30", "2000-09-06", "2005-12-17",
"2010-10-28", "2015-10-18", "2020-12-02", "2025-03-27")
landsat_images_mo <- function(i){
plotRGB(landsat_image_mo_list[[i]], r = 3, g = 2, b = 1, stretch = "lin")
mtext(paste("Date:", layer_date[i], "\nCreated by: Jiatong Su"),
side = 1, line = -1.5, adj = 0.5, cex = 0.5, col = "white", font=2)
}
Some images show minor cloud cover; however, these were the
highest-quality sennes avaliable for each year and were therefore
selected to ensure consistency arcoss the time series. The following
Landsat images highlight the significant growth of Macau’s land area in
recent decades.
下列 Landsat 影像展示了澳門自 1990 年以來的明顯填海過程。
par(mfrow = c(2, 4), mar = c(2, 2, 3, 1))
for(i in seq_along(landsat_image_mo_list)){
landsat_images_mo(i)
}

NDWI
Using
Normalized Difference Water Index (NDWI)
NDWI = (Green – NIR)/(Green + NIR)
NDWI <- function(green, NIR){
value <- (green - NIR) / (green + NIR)
return(value)
}
The NDWI values correspond to the following
ranges:
0,2 – 1 – Water surface,
0.0 – 0,2 – Flooding, humidity,
-0,3 – 0.0 – Moderate drought, non-aqueous surfaces,
-1 – -0.3 – Drought, non-aqueous surfaces
ndwi_1990 <- NDWI(crop_1990$green, crop_1990$NIR)
ndwi_1995 <- NDWI(crop_1995$green, crop_1995$NIR)
ndwi_2000 <- NDWI(crop_2000$green, crop_2000$NIR)
ndwi_2005 <- NDWI(crop_2005$green, crop_2005$NIR)
ndwi_2010 <- NDWI(crop_2010$green, crop_2010$NIR)
ndwi_2015 <- NDWI(crop_2015$green, crop_2015$NIR)
ndwi_2020 <- NDWI(crop_2020$green, crop_2020$NIR)
ndwi_2025 <- NDWI(crop_2025$green, crop_2025$NIR)
In 1969, a 2.2-kilometer causeway known as Estrada
do Istmo (路氹連貫公路) was constructed to connect Taipa and
Coloane.
After the completion of Estrada
do Istmo (路氹連貫公路) causeway, the east-west movement of
water and sediment between Taipa and
Coloane
was obstructed. this alteration in hydrodynamic condition led to
accelerated sediment deposition in both side of causeway, especially on
the western side. Within a short period, extensive tidal flats emerged,
and mangroves proliferated rapidly. These geomorphological changes
created favorable conditions for subsequent large-scale land
reclamation. (城市格局演變與城市規劃制度研析)
Therefore, the following NDWI image shows that the western side of
the causeway exhibits lower NDWI values, indicating significant sediment
deposition in that area.
plot(ndwi_1990)
mtext("1990-12-24\nAuthor: Jiatong Su", side = 1, line = -1.5, adj = 0.5, cex = 0.5, col = "white", font=2)

However, this is not as apparent in the visible RGB Landsat imagery,
where the western side of the causeway still appears to be normal
water.
plotRGB( crop_1990, r = 3, g = 2, b = 1, stretch = "lin")
mtext("1990-12-24\nAuthor: Jiatong Su", side = 1, line = -1.5, adj = 0.5, cex = 0.5, col = "white", font=2)

stack_ndwi <- stack(ndwi_1990, ndwi_1995, ndwi_2000, ndwi_2005,
ndwi_2010, ndwi_2015, ndwi_2020, ndwi_2025)
names(stack_ndwi) <- c("ndwi_1990", "ndwi_1995", "ndwi_2000", "ndwi_2005",
"ndwi_2010", "ndwi_2015", "ndwi_2020", "ndwi_2025")
plot(stack_ndwi)

False color
land_mask <- ndwi_rast <= 0
land_mask01 <- classify(land_mask, cbind(0, NA, 1))
land_stack <- c(land_mask01[[1]], land_mask01[[2]], land_mask01[[3]],
land_mask01[[4]], land_mask01[[5]], land_mask01[[6]],
land_mask01[[7]], land_mask01[[8]] )
names(land_stack) <- c("land_1990","land_1995","land_2000",
"land_2005","land_2010","land_2015",
"land_2020","land_2025")
#plotRGB(land_stack, r=3, g=2, b=1, stretch="lin") # 1995 vs 1990
plotRGB(land_stack, r=4, g=2, b=2, stretch="lin") # 1995 vs 2025
#mtext( "Created by Jiatong Su", side=1, adj=0.6, line=4, cex=1.5, col = "grey")
#mtext( "2000-09-06", cex.main=1, adj=0.6, cex=2, col = "grey")
mtext(paste("Date:", "1995 vs 2005", "\nCreated by: Jiatong Su"),
side = 1, cex.main=1, adj=0.6, line=4, cex=1.5, col = "white", font=2)

false color 00-10-25
This false-color land-change visualization highlights Macau’s rapid
coastal expansion from 2000 to 2025 using multi-temporal Landsat
imagery. Red areas represent newly reclaimed land between 2010–2025,
yellow between 2000–2010, and white denotes stable land present across
all three period.
# 取得 raster 的座標範圍
e <- terra::ext(land_stack)
# 設定 legend 位置(右下角內縮 5%)
x_leg <- e$xmax - 0.5 * (e$xmax - e$xmin)
y_leg <- e$ymax - 0.1 * (e$ymax - e$ymin) # ymin 是下面 → 往上 20%
# plot
plotRGB(
land_stack, r = 8, g = 5, b = 3, stretch = "lin",
main = "Macau Land Expansion (2000–2010–2025)")
mtext(
"False-color Representation\nof Macau Land Expansion\n2000 • 2010 • 2025",
side = 1, # top
line = 2, # move closer to plot (- moves inside)
adj = 0.6,
cex = 1.5,
font = 1,
col = "white" )
# Caption
mtext(
"Created by Jiatong Su",
side = 1,
line = 4,
adj = 0.62,
cex = 1,
col = "grey")
legend(
x = x_leg,
y = y_leg,
legend = c(
"Change between 2010-2025",
"Change between 2000-2010",
"Land in all 3 periods"
#"Water"
),
fill = c(
rgb(1,0,0), # red for 2025
rgb(1,1,0), # yellow for 2000-2010
rgb(1,1,1) # white in all period
#rgb(0,0,0) # black is water
),
border = NA,
cex = 0.85,
bg = NA,
text.col = "white",
bty = "n" )

Interactive map
#only one color represent land,water is NA
pal_land <- colorFactor(
palette = c("orange"),
domain = c(1),
na.color = "transparent"
)
years <- c("1990","1995","2000","2005","2010","2015","2020","2025")
layer_names <- names(land_stack) # "land_1990" ...
m <- leaflet() |>
addProviderTiles(providers$CartoDB.Positron) # basemap
# add land mask for each year
for (i in seq_along(layer_names)) {
m <- m |>
addRasterImage(
land_stack[[i]],
colors = pal_land,
opacity = 0.8,
project = TRUE, # WGS84 - leaflet
group = years[i]
)
}
# layer control(chose year)
m <- m |>
addLayersControl(
overlayGroups = years,
options = layersControlOptions(collapsed = FALSE)
) |>
addControl(
"NDWI-based Land Mask for Macau (1990–2025)",
position = "bottomleft"
)
m
LS0tDQp0aXRsZTogIk1hY2F1LXJlY2xhbWF0aW9uLXRpbWVzZXJpZXMiICAgDQphdXRob3I6ICJKaWF0b25nIFN1IiAgICAgICAgICAgICAgICAgICAgIA0KDQpvdXRwdXQ6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMg5oyH5a6a6Ly45Ye65qC85byPDQogIGh0bWxfZG9jdW1lbnQ6ICAgICAgICAgICAgICAgICAgICAgICAgICMg5L2/55SoIHJtYXJrZG93bjo6aHRtbF9kb2N1bWVudCgpIOi8uOWHuiBIVE1MDQogICAgdGhlbWU6IHNpbXBsZXggICAgICAgICAgICAgICAgICAgICAgICMg5L2/55SoIEJvb3Rzd2F0Y2gg55qEICdzaW1wbGV4JyDkuLvpoYzmqKPlvI8NCiAgICB0b2M6IHRydWUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyDmmK/lkKbpoa/npLrnm67pjIQgKHRhYmxlIG9mIGNvbnRlbnRzKQ0KICAgIHRvY19mbG9hdDogdHJ1ZSAgICAgICAgICAgICAgICAgICAgICAjIOebrumMhOWbuuWumuWcqOWBtOmCiu+8jOaNsuWLlemggemdouaZguacg+i3n+iRl+WLlQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZSAgICAgICAgICAgICAgICAgICAjIFIgY29kZSDpoJDoqK3mkbrnlorvvIzoroDogIXlj6/mjInmjInpiJXlsZXplosNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMgICAgICAgICAgICAgICAgICAjIGRvd25sb2FkIFJtZA0KDQpwYXJhbXM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMga25pdCB3aXRoIHBhcmFtZXRlcnMg55So55qE5Y+D5pW46Kit5a6aDQogIGluY2x1ZGVfd2FybmluZ3M6IGZhbHNlICAgICAgIA0KDQplZGl0b3Jfb3B0aW9uczogICAgICAgICAgICAgICAgICAgICAgICAgICMg5Y+q5b2x6Z+/IFJTdHVkaW8g57eo6Lyv5Zmo77yM5LiN5b2x6Z+/6Ly45Ye657WQ5p6cDQogIG1hcmtkb3duOg0KICAgIHdyYXA6IHNlbnRlbmNlICAgICAgICAgICAgICAgICAjIOWcqCBSU3R1ZGlvIOijoeiHquWLleS+neOAjOWPpeWtkOOAjeaPm+ihjO+8jOaWueS+v+Wvq+mVt+aWhw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KI3JtKGxpc3QgPSBscygpKQ0KI3NldHdkKCdDOi9Vc2Vycy81OTIzOS9EZXNrdG9wL21hY2F1JykNCmxpYnJhcnkocmFzdGVyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkoYW5pbWF0aW9uKQ0KbGlicmFyeShtYWdpY2spDQpsaWJyYXJ5KHRlcnJhKQ0KbGlicmFyeShsZWFmbGV0KQ0KbGlicmFyeSh0ZXJyYSkNCmxpYnJhcnkobWFnaWNrKQ0KDQoNCmBgYA0KDQojIEludHJvZHVjdGlvbg0KDQpNYWNhdSBoYXMgdW5kZXJnb25lIHNpZ25pZmljYW50IGxhbmQgcmVjbGFtYXRpb24gb3ZlciB0aGUgbGFzdCBmZXcgZGVjYWRlcy4NCkR1ZSB0byB1cmJhbiBncm93dGggYW5kIGxpbWl0ZWQgb3JpZ2luYWwgbGFuZCBhcmVhLCByZWNsYW1hdGlvbiBoYXMgcGxheWVkIGEgZG9taW5hbnQgcm9sZSBpbiBzaGFwaW5nIHRoZSBjaXR5J3MgbW9kZXJuIGxhbmRzY2FwZS4NClRoaXMgc3R1ZHkgdXRpbGl6ZXMgTGFuZHNhdCBpbWFnZXJ5IHRvIHZpc3VhbGl6ZSBhbmQgcXVhbnRpZnkgbGFuZCBleHBhbnNpb24gZnJvbSAxOTkwIHRvIDIwMjUsIGV4YW1pbmluZyB0aGUgdGVtcG9yYWwgZXZvbHV0aW9uIG9mIE1hY2F1J3MgbGFuZCBleHRlbnQuDQoNCuacrOeglOeptumBi+eUqCBMYW5kc2F0IOW9seWDj+WRiOePvuS4puWIhuaekOa+s+mWgOmBjuWOu+S4ieWNgeWkmuW5tOS+hueahOWcn+WcsOaTtOW8teOAgg0KDQojIERhdGENCg0KVGhlIFttYWNhdV9nZW9qc29uXShodHRwczovL2dlbzJkYXkuY29tL2FzaWEvY2hpbmEvbWFjYXUuZ2VvanNvbikgd2FzIGRvd25sb2FkZWQgZnJvbSB0aGUgW01hcCBvZiBNYWNhdSBhbmQgR0lTIGRhdGEg4oCUIGRvd25sb2FkIE9TTSB2ZWN0b3IgbGF5ZXJzXShodHRwczovL2dlbzJkYXkuY29tL2FzaWEvY2hpbmEvbWFjYXUuaHRtbCkgYW5kIHVzZWQgYXMgdGhlIHNwYXRpYWwgYm91bmRhcnkgZm9yIGNyb3BwaW5nIHRoZSBMYW5kc2F0IGltYWdlcnkuDQpUaGlzIHBvbHlnb24gYm91bmRhcnkgaXMgdXNlZCB0byBjcm9wIGVhY2ggTGFuZHNhdCBzY2VuZSB0byB0aGUgc3R1ZHkgYXJlYS4NCg0KYGBge3IgbWFjYXVfcG9seWdvbn0NCm1hY2F1X3BvbHlnb24gPC0gc3RfcmVhZCgiaHR0cHM6Ly9nZW8yZGF5LmNvbS9hc2lhL2NoaW5hL21hY2F1Lmdlb2pzb24iKQ0KcGxvdChtYWNhdV9wb2x5Z29uKQ0KYGBgDQoNCiMgTGFuZHNhdCBpbWFnZXJ5IGZyb20gMTk5MC0yMDI1DQoNClRoZSBhbmFseXNpcyB1c2VzIG11bHRpLXRlbXBvcmFsIExhbmRzYXQgaW1hZ2VyeSBmcm9tIDE5OTAtMjAyNSwgZG93bmxvYWRlZCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIEdlb2xvZ2ljYWwgU3VydmV5KFVTR1MpIFtFYXJ0aEV4cGxvcmVyXShodHRwczovL2VhcnRoZXhwbG9yZXIudXNncy5nb3YvKSBQbGF0ZnJvbS4NClRoZSBMYW5kc2F0IGRhdGEgb2YgZWFjaCB5ZWFyIGNvbnRhaW5zIG11bHRpcGxlIHNpbmdsZSBiYW5kIGB0aWZgIGZpbGVzLg0KVGhlc2UgYmFuZHMgbXVzdCBiZSBzdGFja2VkIGludG8gYSBtdWx0aS1iYW5kIHJhc3RlciBiZWZvcmUgdmlzdWFsaXphdGlvbiBvciBhbmFseXNpcy4NCkZvciBtb3JlIGRldGFpbCBpbmZvcm1hdGlvbiBhYm91dCBMYW5kc2F0IHNwZWN0cmFsIGJhbmRzLCByZWZlciB0byBbU3BlY3RyYWwgQmFuZHMgYW5kIEFwcGxpY2F0aW9ucyAtIE5BU0EgU2NpZW5jZV0oaHR0cHM6Ly9zY2llbmNlLm5hc2EuZ292L21pc3Npb24vbGFuZHNhdC9zcGVjdHJhbC1iYW5kcy1hbmQtYXBwbGljYXRpb25zLyl7c3R5bGU9ImZvbnQtc2l6ZTogMTFwdDsifS4NCg0KIyMgTGFuZHNhdDRfMTk5MDEyMjQNCg0KW0xhbmRzYXQ0XShodHRwczovL3d3dy51c2dzLmdvdi9sYW5kc2F0LW1pc3Npb25zL2xhbmRzYXQtNCkNCg0KYGBge3IgbGFuZHNhdDRfMTk5MDEyMjR9DQpsYW5kc2F0NF8xOTkwMTIyNCA8LSBzdGFjaygNCiAiTFQwNF9MMlNQXzEyMjA0NV8xOTkwMTIyNF8yMDIwMDkxNV8wMl9UMS9MVDA0X0wyU1BfMTIyMDQ1XzE5OTAxMjI0XzIwMjAwOTE1XzAyX1QxX1NSX0IxLlRJRiIsDQogIkxUMDRfTDJTUF8xMjIwNDVfMTk5MDEyMjRfMjAyMDA5MTVfMDJfVDEvTFQwNF9MMlNQXzEyMjA0NV8xOTkwMTIyNF8yMDIwMDkxNV8wMl9UMV9TUl9CMi5USUYiLA0KICJMVDA0X0wyU1BfMTIyMDQ1XzE5OTAxMjI0XzIwMjAwOTE1XzAyX1QxL0xUMDRfTDJTUF8xMjIwNDVfMTk5MDEyMjRfMjAyMDA5MTVfMDJfVDFfU1JfQjMuVElGIiwNCiAiTFQwNF9MMlNQXzEyMjA0NV8xOTkwMTIyNF8yMDIwMDkxNV8wMl9UMS9MVDA0X0wyU1BfMTIyMDQ1XzE5OTAxMjI0XzIwMjAwOTE1XzAyX1QxX1NSX0I0LlRJRiIsDQogIkxUMDRfTDJTUF8xMjIwNDVfMTk5MDEyMjRfMjAyMDA5MTVfMDJfVDEvTFQwNF9MMlNQXzEyMjA0NV8xOTkwMTIyNF8yMDIwMDkxNV8wMl9UMV9TUl9CNS5USUYiLA0KICJMVDA0X0wyU1BfMTIyMDQ1XzE5OTAxMjI0XzIwMjAwOTE1XzAyX1QxL0xUMDRfTDJTUF8xMjIwNDVfMTk5MDEyMjRfMjAyMDA5MTVfMDJfVDFfU1RfQjYuVElGIiwNCiAiTFQwNF9MMlNQXzEyMjA0NV8xOTkwMTIyNF8yMDIwMDkxNV8wMl9UMS9MVDA0X0wyU1BfMTIyMDQ1XzE5OTAxMjI0XzIwMjAwOTE1XzAyX1QxX1NSX0I3LlRJRiINCg0KKQ0KDQpuYW1lcyhsYW5kc2F0NF8xOTkwMTIyNCkgPC0gYygiYmx1ZSIsICJncmVlbiIsICJyZWQiLCAiTklSIiwgIlNXSVIiLCJUaGVybWFsIiwgIk1pZC1JbmZyYXJlZC1JUiIpICNyZW5hbWUgYmFuZHMNCg0KIyBwbG90UkdCKGxhbmRzYXQ0XzE5OTAxMjI0LCByPTMsIGcgPSAyLCBiID0gMSwgc3RyZXRjaCA9ICJsaW4iKQ0KDQpzdW1tYXJ5KGxhbmRzYXQ0XzE5OTAxMjI0KQ0KDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmNycyhsYW5kc2F0NF8xOTkwMTIyNCkNCnN1bW1hcnkobGFuZHNhdDRfMTk5MDEyMjQpDQpgYGANCg0KIyMgTGFuZHNhdDVfMTk5NQ0KDQpbTGFuZHNhdDVdKGh0dHBzOi8vd3d3LnVzZ3MuZ292L2xhbmRzYXQtbWlzc2lvbnMvbGFuZHNhdC01KQ0KDQpgYGB7ciBsYW5kc2F0NV8xOTk1fQ0KbGFuZHNhdDVfMTk5NTEyMzAgPC0gc3RhY2soDQogICJMVDA1X0wyU1BfMTIyMDQ1XzE5OTUxMjMwXzIwMjAwOTExXzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMTk5NTEyMzBfMjAyMDA5MTFfMDJfVDFfU1JfQjEuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMTk5NTEyMzBfMjAyMDA5MTFfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8xOTk1MTIzMF8yMDIwMDkxMV8wMl9UMV9TUl9CMi5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8xOTk1MTIzMF8yMDIwMDkxMV8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzE5OTUxMjMwXzIwMjAwOTExXzAyX1QxX1NSX0IzLlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzE5OTUxMjMwXzIwMjAwOTExXzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMTk5NTEyMzBfMjAyMDA5MTFfMDJfVDFfU1JfQjQuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMTk5NTEyMzBfMjAyMDA5MTFfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8xOTk1MTIzMF8yMDIwMDkxMV8wMl9UMV9TUl9CNS5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8xOTk1MTIzMF8yMDIwMDkxMV8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzE5OTUxMjMwXzIwMjAwOTExXzAyX1QxX1NUX0I2LlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzE5OTUxMjMwXzIwMjAwOTExXzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMTk5NTEyMzBfMjAyMDA5MTFfMDJfVDFfU1JfQjcuVElGIg0KKQ0KDQpuYW1lcyhsYW5kc2F0NV8xOTk1MTIzMCkgPC0gYygiYmx1ZSIsICJncmVlbiIsICJyZWQiLCAiTklSIiwgIlNXSVIiLCAiVGhlcm1hbCIsICJNaWQtSW5mcmFyZWQiKSAjcmVuYW1lIGJhbmRzDQoNCnN1bW1hcnkobGFuZHNhdDVfMTk5NTEyMzApDQoNCiNjcnMobGFuZHNhdDVfMTk5NTEyMzApDQoNCmBgYA0KDQojIyBMYW5kc2F0NV8yMDAwDQoNCmBgYHtyIExhbmRzYXQ1XzIwMDB9DQpMYW5kc2F0NV8yMDAwMDkwNiA8LSBzdGFjaygNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAwMDA5MDZfMjAyMDA5MDZfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDAwMDkwNl8yMDIwMDkwNl8wMl9UMV9TUl9CMS5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDAwMDkwNl8yMDIwMDkwNl8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMDAwOTA2XzIwMjAwOTA2XzAyX1QxX1NSX0IyLlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMDAwOTA2XzIwMjAwOTA2XzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAwMDA5MDZfMjAyMDA5MDZfMDJfVDFfU1JfQjMuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAwMDA5MDZfMjAyMDA5MDZfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDAwMDkwNl8yMDIwMDkwNl8wMl9UMV9TUl9CNC5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDAwMDkwNl8yMDIwMDkwNl8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMDAwOTA2XzIwMjAwOTA2XzAyX1QxX1NSX0I1LlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMDAwOTA2XzIwMjAwOTA2XzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAwMDA5MDZfMjAyMDA5MDZfMDJfVDFfU1RfQjYuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAwMDA5MDZfMjAyMDA5MDZfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDAwMDkwNl8yMDIwMDkwNl8wMl9UMV9TUl9CNy5USUYiDQopDQoNCm5hbWVzKExhbmRzYXQ1XzIwMDAwOTA2KSA8LSBjKCJibHVlIiwgImdyZWVuIiwgInJlZCIsICJOSVIiLCAiU1dJUiIsICJUaGVybWFsIiwgIk1pZC1JbmZyYXJlZCIpICNyZW5hbWUgYmFuZHMNCg0Kc3VtbWFyeShMYW5kc2F0NV8yMDAwMDkwNikNCg0KYGBgDQoNCiMjIExhbmRzYXQ1XzIwMDUNCg0KW0xhbmRzYXQ3XShodHRwczovL3d3dy51c2dzLmdvdi9sYW5kc2F0LW1pc3Npb25zL2xhbmRzYXQtNykgY2FuIG5vdCB1c2UNCg0KYGBge3IgTGFuZHNhdDVfMjAwNX0NCkxhbmRzYXQ1XzIwMDUxMDIyIDwtIHN0YWNrKA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDA1MTAyMl8yMDIwMDkwMV8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMDUxMDIyXzIwMjAwOTAxXzAyX1QxX1NSX0IxLlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMDUxMDIyXzIwMjAwOTAxXzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAwNTEwMjJfMjAyMDA5MDFfMDJfVDFfU1JfQjIuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAwNTEwMjJfMjAyMDA5MDFfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDA1MTAyMl8yMDIwMDkwMV8wMl9UMV9TUl9CMy5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDA1MTAyMl8yMDIwMDkwMV8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMDUxMDIyXzIwMjAwOTAxXzAyX1QxX1NSX0I0LlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMDUxMDIyXzIwMjAwOTAxXzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAwNTEwMjJfMjAyMDA5MDFfMDJfVDFfU1JfQjUuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAwNTEwMjJfMjAyMDA5MDFfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDA1MTAyMl8yMDIwMDkwMV8wMl9UMV9TVF9CNi5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDA1MTAyMl8yMDIwMDkwMV8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMDUxMDIyXzIwMjAwOTAxXzAyX1QxX1NSX0I3LlRJRiINCiAgKQ0KDQpuYW1lcyhMYW5kc2F0NV8yMDA1MTAyMikgPC0gYygiYmx1ZSIsICJncmVlbiIsICJyZWQiLCAiTklSIiwgIlNXSVIiLCAiVGhlcm1hbCIsICJNaWQtSW5mcmFyZWQiKSAjcmVuYW1lIGJhbmRzDQoNCnN1bW1hcnkoTGFuZHNhdDVfMjAwNTEwMjIpDQoNCmBgYA0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCnBsb3RSR0IoTGFuZHNhdDVfMjAwNTEwMjIsIHIgPSAzLCBnID0gMiwgYiA9IDEsIHN0cmV0Y2ggPSAibGluIikNCmBgYA0KDQojIyBMYW5kc2F0NV8yMDEwDQoNCmBgYHtyIExhbmRzYXQ1XzIwMTB9DQpMYW5kc2F0NV8yMDEwMDMyNiA8LSBzdGFjaygNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAxMDAzMjZfMjAyMDA4MjRfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDEwMDMyNl8yMDIwMDgyNF8wMl9UMV9TUl9CMS5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDEwMDMyNl8yMDIwMDgyNF8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMTAwMzI2XzIwMjAwODI0XzAyX1QxX1NSX0IyLlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMTAwMzI2XzIwMjAwODI0XzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAxMDAzMjZfMjAyMDA4MjRfMDJfVDFfU1JfQjMuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAxMDAzMjZfMjAyMDA4MjRfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDEwMDMyNl8yMDIwMDgyNF8wMl9UMV9TUl9CNC5USUYiLA0KICAiTFQwNV9MMlNQXzEyMjA0NV8yMDEwMDMyNl8yMDIwMDgyNF8wMl9UMS9MVDA1X0wyU1BfMTIyMDQ1XzIwMTAwMzI2XzIwMjAwODI0XzAyX1QxX1NSX0I1LlRJRiIsDQogICJMVDA1X0wyU1BfMTIyMDQ1XzIwMTAwMzI2XzIwMjAwODI0XzAyX1QxL0xUMDVfTDJTUF8xMjIwNDVfMjAxMDAzMjZfMjAyMDA4MjRfMDJfVDFfU1RfQjYuVElGIiwNCiAgIkxUMDVfTDJTUF8xMjIwNDVfMjAxMDAzMjZfMjAyMDA4MjRfMDJfVDEvTFQwNV9MMlNQXzEyMjA0NV8yMDEwMDMyNl8yMDIwMDgyNF8wMl9UMV9TUl9CNy5USUYiDQopDQoNCm5hbWVzKExhbmRzYXQ1XzIwMTAwMzI2KSA8LSBjKCJibHVlIiwgImdyZWVuIiwgInJlZCIsICJOSVIiLCAiU1dJUiIsICJUaGVybWFsIiwgIk1pZC1JbmZyYXJlZCIpICNyZW5hbWUgYmFuZHMNCg0Kc3VtbWFyeShMYW5kc2F0NV8yMDEwMDMyNikNCmBgYA0KDQojIyBMYW5kc2F0OF8yMDE1DQoNCltMYW5kc2F0OF0oaHR0cHM6Ly93d3cudXNncy5nb3YvbGFuZHNhdC1taXNzaW9ucy9sYW5kc2F0LTgpDQoNCmBgYHtyIExhbmRzYXQ4XzIwMTV9DQpMYW5kc2F0OF8yMDE1MTAxOCA8LSBzdGFjaygNCiAjIkxDMDhfTDJTUF8xMjIwNDVfMjAxNTEwMThfMjAyMDA5MDhfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMV9TUl9CMS5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMTUxMDE4XzIwMjAwOTA4XzAyX1QxX1NSX0IyLlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMTUxMDE4XzIwMjAwOTA4XzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAxNTEwMThfMjAyMDA5MDhfMDJfVDFfU1JfQjMuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAxNTEwMThfMjAyMDA5MDhfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMV9TUl9CNC5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMTUxMDE4XzIwMjAwOTA4XzAyX1QxX1NSX0I1LlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMTUxMDE4XzIwMjAwOTA4XzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAxNTEwMThfMjAyMDA5MDhfMDJfVDFfU1JfQjYuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAxNTEwMThfMjAyMDA5MDhfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMV9TUl9CNy5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDE1MTAxOF8yMDIwMDkwOF8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMTUxMDE4XzIwMjAwOTA4XzAyX1QxX1NUX0IxMC5USUYiDQopDQoNCm5hbWVzKExhbmRzYXQ4XzIwMTUxMDE4KSA8LSBjKCAiYmx1ZSIsICJncmVlbiIsICJyZWQiLCAiTklSIiwgIlNXSVIiLCAiU1dJUjIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUSVJTMSIpICNyZW5hbWUgYmFuZHMNCg0KI1RoZXJtYWwgSW5mcmFyZWQgU2Vuc29yIChUSVJTKTogQmFuZCAxMCBUSVJTIDEgKDEwLjYgLSAxMS4xOSDCtW0pIDEwMCBtDQojIkNvYXN0YWwiID0gQmFuZCAxDQpzdW1tYXJ5KExhbmRzYXQ4XzIwMTUxMDE4KQ0KYGBgDQoNCiMjIExhbmRzYXQ4XzIwMjANCg0KYGBge3IgTGFuZHNhdDhfMjAyMH0NCkxhbmRzYXQ4XzIwMjAxMjAyIDwtIHN0YWNrKA0KICMiTEMwOF9MMlNQXzEyMjA0NV8yMDIwMTIwMl8yMDIxMDMxMl8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxX1NSX0IxLlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAyMDEyMDJfMjAyMTAzMTJfMDJfVDFfU1JfQjIuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAyMDEyMDJfMjAyMTAzMTJfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDIwMTIwMl8yMDIxMDMxMl8wMl9UMV9TUl9CMy5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDIwMTIwMl8yMDIxMDMxMl8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxX1NSX0I0LlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAyMDEyMDJfMjAyMTAzMTJfMDJfVDFfU1JfQjUuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAyMDEyMDJfMjAyMTAzMTJfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDIwMTIwMl8yMDIxMDMxMl8wMl9UMV9TUl9CNi5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDIwMTIwMl8yMDIxMDMxMl8wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxX1NSX0I3LlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMjAxMjAyXzIwMjEwMzEyXzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAyMDEyMDJfMjAyMTAzMTJfMDJfVDFfU1RfQjEwLlRJRiINCikNCg0KDQpuYW1lcyhMYW5kc2F0OF8yMDIwMTIwMikgPC0gYyggImJsdWUiLCAiZ3JlZW4iLCAicmVkIiwgIk5JUiIsICJTV0lSIiwgIlNXSVIyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVElSUzEiKSAjcmVuYW1lIGJhbmRzDQoNCiNUaGVybWFsIEluZnJhcmVkIFNlbnNvciAoVElSUyk6IEJhbmQgMTAgVElSUyAxICgxMC42IC0gMTEuMTkgwrVtKSAxMDAgbQ0KDQpzdW1tYXJ5KExhbmRzYXQ4XzIwMjAxMjAyKQ0KYGBgDQoNCiMjIExhbmRzYXQ4XzIwMjUwMzI3DQoNCmBgYHtyIExhbmRzYXQ4XzIwMjUwMzI3fQ0KTGFuZHNhdDhfMjAyNTAzMjcgPC0gc3RhY2soDQojIkxDMDhfTDJTUF8xMjIwNDVfMjAyNTAzMTlfMjAyNTAzMjdfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMV9TUl9CMS5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjUwMzE5XzIwMjUwMzI3XzAyX1QxX1NSX0IyLlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMjUwMzE5XzIwMjUwMzI3XzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAyNTAzMTlfMjAyNTAzMjdfMDJfVDFfU1JfQjMuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAyNTAzMTlfMjAyNTAzMjdfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMV9TUl9CNC5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjUwMzE5XzIwMjUwMzI3XzAyX1QxX1NSX0I1LlRJRiIsDQogICJMQzA4X0wyU1BfMTIyMDQ1XzIwMjUwMzE5XzIwMjUwMzI3XzAyX1QxL0xDMDhfTDJTUF8xMjIwNDVfMjAyNTAzMTlfMjAyNTAzMjdfMDJfVDFfU1JfQjYuVElGIiwNCiAgIkxDMDhfTDJTUF8xMjIwNDVfMjAyNTAzMTlfMjAyNTAzMjdfMDJfVDEvTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMV9TUl9CNy5USUYiLA0KICAiTEMwOF9MMlNQXzEyMjA0NV8yMDI1MDMxOV8yMDI1MDMyN18wMl9UMS9MQzA4X0wyU1BfMTIyMDQ1XzIwMjUwMzE5XzIwMjUwMzI3XzAyX1QxX1NUX0IxMC5USUYiDQopDQoNCm5hbWVzKExhbmRzYXQ4XzIwMjUwMzI3KSA8LSBjKCAiYmx1ZSIsICJncmVlbiIsICJyZWQiLCAiTklSIiwgIlNXSVIiLCAiU1dJUjIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUSVJTMSIpICNyZW5hbWUgYmFuZHMNCg0KDQpzdW1tYXJ5KExhbmRzYXQ4XzIwMjUwMzI3KQ0KDQpgYGANCg0KIyBDcm9wDQoNClRoaXMgc2VjdGlvbiB1c2UgbWFjYXUgYm91bmRhcnkgcG9seWdvbiB0byBjcm9wIHRoZSBzdHVkeSBhcmVhIGZyb20gZWFjaCB5ZWFyIExhbmRzYXQgc3RhY2tlZCBpbWFnZS4NCg0KYGBge3J9DQptYWNhdV9wb2x5X3V0bSA8LSBzdF90cmFuc2Zvcm0obWFjYXVfcG9seWdvbiwgY3JzID0gY3JzKExhbmRzYXQ1XzIwMDUxMDIyKSkNCiMgbWF0Y2ggdGhlIHByb2plY3Rpb24NCmBgYA0KDQpgYGB7ciBjcm9wfQ0KY3JvcF8xOTkwIDwtIGNyb3AobGFuZHNhdDRfMTk5MDEyMjQsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8xOTk1IDwtIGNyb3AobGFuZHNhdDVfMTk5NTEyMzAsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDAwIDwtIGNyb3AoTGFuZHNhdDVfMjAwMDA5MDYsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDA1IDwtIGNyb3AoTGFuZHNhdDVfMjAwNTEwMjIsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDEwIDwtIGNyb3AoTGFuZHNhdDVfMjAxMDAzMjYsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDE1IDwtIGNyb3AoTGFuZHNhdDhfMjAxNTEwMTgsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDIwIDwtIGNyb3AoTGFuZHNhdDhfMjAyMDEyMDIsIG1hY2F1X3BvbHlfdXRtKQ0KY3JvcF8yMDI1IDwtIGNyb3AoTGFuZHNhdDhfMjAyNTAzMjcsIG1hY2F1X3BvbHlfdXRtKQ0KDQoNCmBgYA0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCnBsb3RSR0IoIGNyb3BfMTk5MCwgciA9IDMsIGcgPSAyLCBiID0gMSwgc3RyZXRjaCA9ICJsaW4iKSANCm10ZXh0KCIxOTkwLTEyLTI0XG5BdXRob3I6IEppYXRvbmcgU3UiLCBzaWRlID0gMSwgbGluZSA9IC0xLjUsIGFkaiA9IDAuNSwgY2V4ID0gMC41LCBjb2wgPSAid2hpdGUiLCBmb250PTIpDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpwbG90UkdCKCBjcm9wXzIwMjUsIHIgPSAzLCBnID0gMiwgYiA9IDEsIHN0cmV0Y2ggPSAibGluIikgDQptdGV4dCgiMjAyNS0wMy0yN1xuQXV0aG9yOiBKaWF0b25nIFN1Iiwgc2lkZSA9IDEsIGxpbmUgPSAtMS41LCBhZGogPSAwLjUsIGNleCA9IDAuNSwgY29sID0gIndoaXRlIiwgZm9udD0yKQ0KDQpgYGANCg0KIyBWaXN1YWxpemF0aW9uDQoNClRydWUgY29sb3IgY29tcG9zaXRlcyB3ZXJlIGdlbmVyYXRlZCBmb3IgZWFjaCB5ZWFyIHVzaW5nIGJhbmQgY29tYmluYXRpb25zIChlLmcuLCBSID0gUmVkLCBHID0gR3JlZW4sIEIgPSBCbHVlKS4NCg0KYGBge3J9DQpsYW5kc2F0X2ltYWdlX21vX2xpc3QgPC0gbGlzdChjcm9wXzE5OTAsIGNyb3BfMTk5NSwgY3JvcF8yMDAwLCBjcm9wXzIwMDUsIGNyb3BfMjAxMCwNCiAgICAgICAgICAgICAgICAgIGNyb3BfMjAxNSwgY3JvcF8yMDIwLCBjcm9wXzIwMjUpDQoNCg0KbGF5ZXJfZGF0ZSA8LSBjKCIxOTkwLTEyLTI0IiwgIjE5OTUtMTItMzAiLCAiMjAwMC0wOS0wNiIsICIyMDA1LTEyLTE3IiwNCiAgICAgICAgICAgICAgIjIwMTAtMTAtMjgiLCAiMjAxNS0xMC0xOCIsICIyMDIwLTEyLTAyIiwgIjIwMjUtMDMtMjciKQ0KDQoNCmxhbmRzYXRfaW1hZ2VzX21vIDwtIGZ1bmN0aW9uKGkpew0KICBwbG90UkdCKGxhbmRzYXRfaW1hZ2VfbW9fbGlzdFtbaV1dLCByID0gMywgZyA9IDIsIGIgPSAxLCBzdHJldGNoID0gImxpbiIpDQogIG10ZXh0KHBhc3RlKCJEYXRlOiIsIGxheWVyX2RhdGVbaV0sICJcbkNyZWF0ZWQgYnk6IEppYXRvbmcgU3UiKSwNCiAgICAgICAgc2lkZSA9IDEsIGxpbmUgPSAtMS41LCBhZGogPSAwLjUsIGNleCA9IDAuNSwgY29sID0gIndoaXRlIiwgZm9udD0yKQ0KfQ0KDQoNCmBgYA0KDQpTb21lIGltYWdlcyBzaG93IG1pbm9yIGNsb3VkIGNvdmVyOyBob3dldmVyLCB0aGVzZSB3ZXJlIHRoZSBoaWdoZXN0LXF1YWxpdHkgc2VubmVzIGF2YWxpYWJsZSBmb3IgZWFjaCB5ZWFyIGFuZCB3ZXJlIHRoZXJlZm9yZSBzZWxlY3RlZCB0byBlbnN1cmUgY29uc2lzdGVuY3kgYXJjb3NzIHRoZSB0aW1lIHNlcmllcy4NClRoZSBmb2xsb3dpbmcgTGFuZHNhdCBpbWFnZXMgaGlnaGxpZ2h0IHRoZSBzaWduaWZpY2FudCBncm93dGggb2YgTWFjYXXigJlzIGxhbmQgYXJlYSBpbiByZWNlbnQgZGVjYWRlcy4NCg0K5LiL5YiXIExhbmRzYXQg5b2x5YOP5bGV56S65LqG5r6z6ZaA6IeqIDE5OTAg5bm05Lul5L6G55qE5piO6aGv5aGr5rW36YGO56iL44CCDQoNCmBgYHtyIHZpc3VhbGl6YXRpb24gZm9yIHZpc2libGUgTGFuZHNhdCBpbWFnZX0NCg0KDQpwYXIobWZyb3cgPSBjKDIsIDQpLCBtYXIgPSBjKDIsIDIsIDMsIDEpKQ0KDQpmb3IoaSBpbiBzZXFfYWxvbmcobGFuZHNhdF9pbWFnZV9tb19saXN0KSl7DQogIGxhbmRzYXRfaW1hZ2VzX21vKGkpDQp9DQoNCg0KYGBgDQoNCg0KDQoNCmBgYHtyIHNhdmUgR0lGLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShhbmltYXRpb24pDQoNCiNUaGUgYGFuaW1hdGlvbmAgZnVuY3Rpb24gaXMgdXNlZCB0byBnZW5lcmF0ZWQgYSBtdWx0aS15ZWFyIGBHSUZgIGlsbHVzdHJhdGluZyB0aGUgcHJvZ3Jzc2lvbiBvZiBsYW5kIGRldmVsb3BtZW50IGFuZCByZWNsYW1hdGlvbiBmcm9tIDE5OTAgdG8gMjAyNS4NCg0Kc2F2ZUdJRih7DQogIGZvciAoaSBpbiBzZXFfYWxvbmcobGFuZHNhdF9pbWFnZV9tb19saXN0KSkgew0KICAgIHBsb3RSR0IobGFuZHNhdF9pbWFnZV9tb19saXN0W1tpXV0sIHIgPSAzLCBnID0gMiwgYiA9IDEsIHN0cmV0Y2ggPSAibGluIikNCiAgICBtdGV4dChwYXN0ZSgiRGF0ZToiLCBsYXllcl9kYXRlW2ldLCAiXG5DcmVhdGVkIGJ5OiBKaWF0b25nIFN1IiksDQogICAgICAgIHNpZGUgPSAxLCBsaW5lID0gLTEuNSwgYWRqID0gMC41LCBjZXggPSAxLjUsIGNvbCA9ICJ3aGl0ZSIsIGZvbnQ9MikNCiAgfQ0KfSwgDQptb3ZpZS5uYW1lID0gIm1hY2F1XzE5OTBfMjAyNS5naWYiLA0KaW50ZXJ2YWwgPSAxLA0KYW5pLndpZHRoID0gODAwLA0KYW5pLmhlaWdodCA9IDgwMA0KKQ0KDQoNCmBgYA0KDQoNCiMgTkRXSQ0KDQpbVXNpbmcgTm9ybWFsaXplZCBEaWZmZXJlbmNlIFdhdGVyIEluZGV4IChORFdJKV0oaHR0cHM6Ly9zdG9yeW1hcHMuYXJjZ2lzLmNvbS9zdG9yaWVzL2Y5NGY1MGMwNWZhMjQ2Njc4NDhiNGI1MWFmNjE0OTM1KQ0KDQoqTkRXSSA9IChHcmVlbiDigJMgTklSKS8oR3JlZW4gKyBOSVIpKg0KDQpgYGB7ciBORFdJIGZ1bmN0aW9ufQ0KDQpORFdJIDwtIGZ1bmN0aW9uKGdyZWVuLCBOSVIpew0KICAgdmFsdWUgPC0gKGdyZWVuIC0gTklSKSAvIChncmVlbiArIE5JUikNCiAgIHJldHVybih2YWx1ZSkNCn0NCg0KYGBgDQoNCioqVGhlIE5EV0kgdmFsdWVzIGNvcnJlc3BvbmQgdG8gdGhlIGZvbGxvd2luZyByYW5nZXM6KioNCg0KLSAgIDAsMiDigJMgMSDigJMgV2F0ZXIgc3VyZmFjZSwNCg0KLSAgIDAuMCDigJMgMCwyIOKAkyBGbG9vZGluZywgaHVtaWRpdHksDQoNCi0gICAtMCwzIOKAkyAwLjAg4oCTIE1vZGVyYXRlIGRyb3VnaHQsIG5vbi1hcXVlb3VzIHN1cmZhY2VzLA0KDQotICAgLTEg4oCTIC0wLjMg4oCTIERyb3VnaHQsIG5vbi1hcXVlb3VzIHN1cmZhY2VzDQoNCmBgYHtyIE5EV0kgfQ0KbmR3aV8xOTkwIDwtIE5EV0koY3JvcF8xOTkwJGdyZWVuLCBjcm9wXzE5OTAkTklSKQ0KbmR3aV8xOTk1IDwtIE5EV0koY3JvcF8xOTk1JGdyZWVuLCBjcm9wXzE5OTUkTklSKQ0KbmR3aV8yMDAwIDwtIE5EV0koY3JvcF8yMDAwJGdyZWVuLCBjcm9wXzIwMDAkTklSKQ0KbmR3aV8yMDA1IDwtIE5EV0koY3JvcF8yMDA1JGdyZWVuLCBjcm9wXzIwMDUkTklSKQ0KbmR3aV8yMDEwIDwtIE5EV0koY3JvcF8yMDEwJGdyZWVuLCBjcm9wXzIwMTAkTklSKQ0KbmR3aV8yMDE1IDwtIE5EV0koY3JvcF8yMDE1JGdyZWVuLCBjcm9wXzIwMTUkTklSKQ0KbmR3aV8yMDIwIDwtIE5EV0koY3JvcF8yMDIwJGdyZWVuLCBjcm9wXzIwMjAkTklSKQ0KbmR3aV8yMDI1IDwtIE5EV0koY3JvcF8yMDI1JGdyZWVuLCBjcm9wXzIwMjUkTklSKQ0KDQoNCmBgYA0KDQpJbiAxOTY5LCBhIDIuMi1raWxvbWV0ZXIgY2F1c2V3YXkga25vd24gYXMgWypFc3RyYWRhIGRvIElzdG1vKiAo6Lev5rC56YCj6LKr5YWs6LevKV0oaHR0cHM6Ly96aC53aWtpcGVkaWEub3JnL3poLW1vLyVFOCVCNyVBRiVFNiVCMCVCOSVFOSU4MCVBMyVFOCVCMiVBQiVFNSU4NSVBQyVFOCVCNyVBRikgd2FzIGNvbnN0cnVjdGVkIHRvIGNvbm5lY3QgW1RhaXBhXShodHRwczovL3poLndpa2lwZWRpYS5vcmcvemgtbW8vJUU2JUIwJUI5JUU0JUJCJTk0KSBhbmQgW0NvbG9hbmVdKGh0dHBzOi8vemgud2lraXBlZGlhLm9yZy96aC1tby8lRTglQjclQUYlRTclOTIlQjApLg0KQWZ0ZXIgdGhlIGNvbXBsZXRpb24gb2YgWypFc3RyYWRhIGRvIElzdG1vKiAo6Lev5rC56YCj6LKr5YWs6LevKV0oaHR0cHM6Ly96aC53aWtpcGVkaWEub3JnL3poLW1vLyVFOCVCNyVBRiVFNiVCMCVCOSVFOSU4MCVBMyVFOCVCMiVBQiVFNSU4NSVBQyVFOCVCNyVBRikgY2F1c2V3YXksIHRoZSBlYXN0LXdlc3QgbW92ZW1lbnQgb2Ygd2F0ZXIgYW5kIHNlZGltZW50IGJldHdlZW4gW1RhaXBhXShodHRwczovL3poLndpa2lwZWRpYS5vcmcvemgtbW8vJUU2JUIwJUI5JUU0JUJCJTk0KSBhbmQgW0NvbG9hbmVdKGh0dHBzOi8vemgud2lraXBlZGlhLm9yZy96aC1tby8lRTglQjclQUYlRTclOTIlQjApIHdhcyBvYnN0cnVjdGVkLg0KdGhpcyBhbHRlcmF0aW9uIGluIGh5ZHJvZHluYW1pYyBjb25kaXRpb24gbGVkIHRvIGFjY2VsZXJhdGVkIHNlZGltZW50IGRlcG9zaXRpb24gaW4gYm90aCBzaWRlIG9mIGNhdXNld2F5LCBlc3BlY2lhbGx5IG9uIHRoZSB3ZXN0ZXJuIHNpZGUuDQpXaXRoaW4gYSBzaG9ydCBwZXJpb2QsIGV4dGVuc2l2ZSB0aWRhbCBmbGF0cyBlbWVyZ2VkLCBhbmQgbWFuZ3JvdmVzIHByb2xpZmVyYXRlZCByYXBpZGx5Lg0KVGhlc2UgZ2VvbW9ycGhvbG9naWNhbCBjaGFuZ2VzIGNyZWF0ZWQgZmF2b3JhYmxlIGNvbmRpdGlvbnMgZm9yIHN1YnNlcXVlbnQgbGFyZ2Utc2NhbGUgbGFuZCByZWNsYW1hdGlvbi4NCihb5Z+O5biC5qC85bGA5ryU6K6K6IiH5Z+O5biC6KaP5YqD5Yi25bqm56CU5p6QXShodHRwczovL3d3dy5oZXJpdGFnZS5tby91cGxvYWRzL3VlZGl0b3IvZmlsZS8yMDI1MDEwOS8xNzM2NDEyODY4NjIwOTU1LnBkZj91dG1fc291cmNlPWNoYXRncHQuY29tKSkNCg0KVGhlcmVmb3JlLCB0aGUgZm9sbG93aW5nIE5EV0kgaW1hZ2Ugc2hvd3MgdGhhdCB0aGUgd2VzdGVybiBzaWRlIG9mIHRoZSBjYXVzZXdheSBleGhpYml0cyBsb3dlciBORFdJIHZhbHVlcywgaW5kaWNhdGluZyBzaWduaWZpY2FudCBzZWRpbWVudCBkZXBvc2l0aW9uIGluIHRoYXQgYXJlYS4NCg0KYGBge3IgbmR3aV8xOTkwfQ0KcGxvdChuZHdpXzE5OTApDQptdGV4dCgiMTk5MC0xMi0yNFxuQXV0aG9yOiBKaWF0b25nIFN1Iiwgc2lkZSA9IDEsIGxpbmUgPSAtMS41LCBhZGogPSAwLjUsIGNleCA9IDAuNSwgY29sID0gIndoaXRlIiwgZm9udD0yKQ0KYGBgDQoNCkhvd2V2ZXIsIHRoaXMgaXMgbm90IGFzIGFwcGFyZW50IGluIHRoZSB2aXNpYmxlIFJHQiBMYW5kc2F0IGltYWdlcnksIHdoZXJlIHRoZSB3ZXN0ZXJuIHNpZGUgb2YgdGhlIGNhdXNld2F5IHN0aWxsIGFwcGVhcnMgdG8gYmUgbm9ybWFsIHdhdGVyLg0KDQpgYGB7ciB2aXNpYmxlIDE5OTB9DQpwbG90UkdCKCBjcm9wXzE5OTAsIHIgPSAzLCBnID0gMiwgYiA9IDEsIHN0cmV0Y2ggPSAibGluIikgDQptdGV4dCgiMTk5MC0xMi0yNFxuQXV0aG9yOiBKaWF0b25nIFN1Iiwgc2lkZSA9IDEsIGxpbmUgPSAtMS41LCBhZGogPSAwLjUsIGNleCA9IDAuNSwgY29sID0gIndoaXRlIiwgZm9udD0yKQ0KYGBgDQoNCmBgYHtyIHN0YWNrIG5kd2l9DQpzdGFja19uZHdpIDwtIHN0YWNrKG5kd2lfMTk5MCwgbmR3aV8xOTk1LCBuZHdpXzIwMDAsIG5kd2lfMjAwNSwNCiAgICAgICAgICAgICAgICAgICAgbmR3aV8yMDEwLCBuZHdpXzIwMTUsIG5kd2lfMjAyMCwgbmR3aV8yMDI1KQ0KDQpuYW1lcyhzdGFja19uZHdpKSA8LSBjKCJuZHdpXzE5OTAiLCAibmR3aV8xOTk1IiwgIm5kd2lfMjAwMCIsICJuZHdpXzIwMDUiLA0KICAgICAgICAgICAgICAgICAgICAgICAibmR3aV8yMDEwIiwgIm5kd2lfMjAxNSIsICJuZHdpXzIwMjAiLCAibmR3aV8yMDI1IikNCmBgYA0KDQpgYGB7ciBwbG90IHN0YWNrIG5kd2l9DQpwbG90KHN0YWNrX25kd2kpDQpgYGANCg0KIyBGYWxzZSBjb2xvcg0KDQpgYGB7ciByYXN0LCBpbmNsdWRlPUZBTFNFfQ0KbmR3aV9yYXN0IDwtIHJhc3Qoc3RhY2tfbmR3aSkNCg0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpwbG90UkdCKG5kd2lfcmFzdCwgciA9IDMsIGcgPSAxLCBiID0gMywgc3RyZXRjaCA9ICJsaW4iKSAjIDIwMDAgdnMgMjAyNQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpwbG90UkdCKG5kd2lfcmFzdCwgciA9IDMsIGcgPSA4LCBiID0gMywgc3RyZXRjaCA9ICJsaW4iKSAjIDIwMDAgdnMgMjAyNQ0KYGBgDQoNCmBgYHtyfQ0KbGFuZF9tYXNrIDwtIG5kd2lfcmFzdCA8PSAwDQoNCmxhbmRfbWFzazAxIDwtIGNsYXNzaWZ5KGxhbmRfbWFzaywgY2JpbmQoMCwgTkEsIDEpKQ0KDQpsYW5kX3N0YWNrIDwtIGMobGFuZF9tYXNrMDFbWzFdXSwgbGFuZF9tYXNrMDFbWzJdXSwgbGFuZF9tYXNrMDFbWzNdXSwNCiAgICAgICAgICAgICAgICBsYW5kX21hc2swMVtbNF1dLCBsYW5kX21hc2swMVtbNV1dLCBsYW5kX21hc2swMVtbNl1dLA0KICAgICAgICAgICAgICAgIGxhbmRfbWFzazAxW1s3XV0sIGxhbmRfbWFzazAxW1s4XV0gKQ0KDQpuYW1lcyhsYW5kX3N0YWNrKSA8LSBjKCJsYW5kXzE5OTAiLCJsYW5kXzE5OTUiLCJsYW5kXzIwMDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAibGFuZF8yMDA1IiwibGFuZF8yMDEwIiwibGFuZF8yMDE1IiwNCiAgICAgICAgICAgICAgICAgICAgICAgImxhbmRfMjAyMCIsImxhbmRfMjAyNSIpDQoNCiNwbG90UkdCKGxhbmRfc3RhY2ssIHI9MywgZz0yLCBiPTEsICBzdHJldGNoPSJsaW4iKSAjIDE5OTUgdnMgMTk5MA0KDQoNCmBgYA0KDQpgYGB7cn0NCnBsb3RSR0IobGFuZF9zdGFjaywgcj00LCBnPTIsIGI9MiwgIHN0cmV0Y2g9ImxpbiIpICMgMTk5NSB2cyAyMDI1DQojbXRleHQoICJDcmVhdGVkIGJ5IEppYXRvbmcgU3UiLCBzaWRlPTEsIGFkaj0wLjYsIGxpbmU9NCwgY2V4PTEuNSwgY29sID0gImdyZXkiKQ0KI210ZXh0KCAiMjAwMC0wOS0wNiIsIGNleC5tYWluPTEsIGFkaj0wLjYsIGNleD0yLCBjb2wgPSAiZ3JleSIpDQoNCiBtdGV4dChwYXN0ZSgiRGF0ZToiLCAiMTk5NSB2cyAyMDA1IiwgIlxuQ3JlYXRlZCBieTogSmlhdG9uZyBTdSIpLA0KICAgICAgICBzaWRlID0gMSwgICBjZXgubWFpbj0xLCBhZGo9MC42LCBsaW5lPTQsIGNleD0xLjUsIGNvbCA9ICJ3aGl0ZSIsIGZvbnQ9MikNCg0KYGBgDQoNCg0KYGBge3IgRmFsc2UgY29sb3IgZ2lmLCBpbmNsdWRlPUZBTFNFfQ0KDQptYWtlX3JnYl9naWYgPC0gZnVuY3Rpb24oc3RhY2ssIGJhbmRzLCB0aXRsZXMsIG91dGZpbGU9InJnYl90aW1lc2VyaWVzLmdpZiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9MTAwMCwgaGVpZ2h0PTEwMDAsIGZwcz0xLCBhdXRob3I9IkNyZWF0ZWQgYnkgSmlhdG9uZyBTdSIpIHsNCiAgDQogIHBuZ19maWxlcyA8LSBjKCkNCiAgDQogIGZvciAoaSBpbiBzZXFfYWxvbmcoYmFuZHMpKSB7DQogICAgDQogICAgIyDmqpTlkI0NCiAgICBmbmFtZSA8LSBwYXN0ZTAoInJnYl8iLCBiYW5kc1tpXSwgIi5wbmciKQ0KICAgIHBuZyhmbmFtZSwgd2lkdGg9d2lkdGgsIGhlaWdodD1oZWlnaHQpDQogICAgDQogICAgIyDnlasgUkdCIOWclg0KICAgIHBsb3RSR0Ioc3RhY2ssIHI9YmFuZHNbaV0sIGc9MiwgYj0yLCBzdHJldGNoPSJsaW4iKQ0KICAgIA0KICAgIG10ZXh0KHBhc3RlKCJEYXRlOiIsIHRpdGxlc1tpXSwgIlxuQ3JlYXRlZCBieTogSmlhdG9uZyBTdSIpLA0KICAgICAgICBzaWRlID0gMSwgbGluZSA9IDQsIGFkaiA9IDAuNiwgY2V4ID0gMiwgY29sID0gIndoaXRlIiwgZm9udD0yKQ0KICAgIGRldi5vZmYoKQ0KICAgIA0KICAgIA0KICAgIHBuZ19maWxlcyA8LSBjKHBuZ19maWxlcywgZm5hbWUpDQogIH0NCiAgDQogICMg6K6A5YWlIFBORyDkuKblkIjmiJAgR0lGDQogIGltZ3MgPC0gaW1hZ2VfcmVhZChwbmdfZmlsZXMpDQogIGdpZiA8LSBpbWFnZV9hbmltYXRlKGltYWdlX2pvaW4oaW1ncyksIGZwcz1mcHMpDQogIGltYWdlX3dyaXRlKGdpZiwgb3V0ZmlsZSkNCiAgDQogIG1lc3NhZ2UoIkdJRiBzYXZlZCBhczogIiwgb3V0ZmlsZSkNCn0NCg0KYGBgDQoNCmBgYHtyIHNhdmUgRmFsc2UgY29sb3IgZ2lmLCBpbmNsdWRlPUZBTFNFfQ0KbWFrZV9yZ2JfZ2lmKA0KICBzdGFjayA9IGxhbmRfc3RhY2ssDQogIGJhbmRzID0gYygyLDQsNiw4KSwgICAgICAgICAgICAgICAgICMg5L2g55qEIHIgPSAyLDQsNiw4DQogIHRpdGxlcyA9IGMoIjE5OTUtMTItMzAiLCAiMjAwMC0wOS0wNiIsICIyMDEwLTEwLTI4IiwgIjIwMjUtMDMtMjciKSwgICAjIOavj+W8tSBQTkcg55qE5qiZ6aGMDQogIG91dGZpbGUgPSAibXlfcmdiLmdpZiIsDQogIGZwcyA9IDEsDQogIGF1dGhvciA9ICJDcmVhdGVkIGJ5IEppYXRvbmcgU3UiDQopDQoNCmBgYA0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCg0KcGxvdFJHQigNCiAgbGFuZF9zdGFjaywgciA9IDEsIGcgPSAyLCBiID0gMywgc3RyZXRjaCA9ICJsaW4iLA0KICBtYWluID0gIk1hY2F1IExhbmQgRXhwYW5zaW9uICgyMDAw4oCTMjAxMOKAkzIwMjUpIg0KKSANCm10ZXh0KA0KICAiRmFsc2UtY29sb3IgcmVwcmVzZW50YXRpb24gb2YgbGFuZCBleHBhbnNpb24uXG5SZWQgPSBOZXcgbGFuZCAoMjAyNSkgXG4gR3JlZW4gPSBsYW5kIGFzIG9mIDIwMTAgXG4gQmx1ZSA9IGxhbmQgYXMgb2YgMjAwMC5cbkNyZWF0ZWQgYnkgSmlhdG9uZyBTdSIsDQogIHNpZGUgPSAxLCBsaW5lID0gNCwgYWRqID0gMC42LCBjZXggPSAwLjcsIGNvbCA9ICJ3aGl0ZSINCikNCmxlZ2VuZCgNCiAgInRvcHJpZ2h0IiwNCiAgbGVnZW5kID0gYygNCiAgICAiTmV3IGxhbmQgKDIwMjUgb25seSkiLA0KICAgICJMYW5kIDIwMTDigJMyMDI1IiwNCiAgICAiTGFuZCAyMDAw4oCTMjAyNSIsDQogICAgIkxhbmQgaW4gYWxsIDMgcGVyaW9kcyIsDQogICAgIldhdGVyIg0KICApLA0KICBmaWxsID0gYygNCiAgICByZ2IoMSwwLDEpLCAgICMg57SrL+a0i+e0hSA9IOaWsOWhq+a1t++8iFI9MSxHPTAsQj0x77yJDQogICAgcmdiKDEsMSwwKSwgICAjIOm7g+iJsiA9IDIwMTAg6IiHIDIwMjUg6YO95piv6Zm45Zyw77yIUj0xLEc9MSxCPTDvvIkNCiAgICByZ2IoMCwxLDEpLCAgICMg6Z2S6ImyID0gMjAwMCAmIDIwMTAgJiAyMDI177yI5Zyo5r6z6ZaA5bm+5LmO5LiN5Ye654++77yJDQogICAgcmdiKDEsMSwxKSwgICAjIOeZveiJsiA9IOWFqOaZguacn+mDveaYr+mZuOWcsA0KICAgIHJnYigwLDAsMCkgICAgIyDpu5HoibIgPSDmtbcNCiAgKSwNCiAgYm9yZGVyID0gTkEsDQogIGNleCA9IDAuOCwNCiAgYmcgPSAid2hpdGUiDQoNCikNCg0KYGBgDQoNCiMjIGZhbHNlIGNvbG9yIDAwLTEwLTI1DQoNClRoaXMgZmFsc2UtY29sb3IgbGFuZC1jaGFuZ2UgdmlzdWFsaXphdGlvbiBoaWdobGlnaHRzIE1hY2F14oCZcyByYXBpZCBjb2FzdGFsIGV4cGFuc2lvbiBmcm9tIDIwMDAgdG8gMjAyNSB1c2luZyBtdWx0aS10ZW1wb3JhbCBMYW5kc2F0IGltYWdlcnkuIFJlZCBhcmVhcyByZXByZXNlbnQgbmV3bHkgcmVjbGFpbWVkIGxhbmQgYmV0d2VlbiAyMDEw4oCTMjAyNSwgeWVsbG93IGJldHdlZW4gMjAwMOKAkzIwMTAsIGFuZCB3aGl0ZSBkZW5vdGVzIHN0YWJsZSBsYW5kIHByZXNlbnQgYWNyb3NzIGFsbCB0aHJlZSBwZXJpb2QuDQoNCmBgYHtyLCBmYWxzZSBjb2xvciBpbWFnZSAwMC0xMC0yNX0NCiAjIOWPluW+lyByYXN0ZXIg55qE5bqn5qiZ56+E5ZyNDQplIDwtIHRlcnJhOjpleHQobGFuZF9zdGFjaykNCg0KIA0KICMg6Kit5a6aIGxlZ2VuZCDkvY3nva7vvIjlj7PkuIvop5LlhafnuK4gNSXvvIkNCiB4X2xlZyA8LSBlJHhtYXggLSAwLjUgKiAoZSR4bWF4IC0gZSR4bWluKQ0KIHlfbGVnIDwtIGUkeW1heCAtIDAuMSAqIChlJHltYXggLSBlJHltaW4pICAjIHltaW4g5piv5LiL6Z2iIOKGkiDlvoDkuIogMjAlDQogDQogIyBwbG90DQogcGxvdFJHQigNCiAgIGxhbmRfc3RhY2ssIHIgPSA4LCBnID0gNSwgYiA9IDMsIHN0cmV0Y2ggPSAibGluIiwNCiAgbWFpbiA9ICJNYWNhdSBMYW5kIEV4cGFuc2lvbiAoMjAwMOKAkzIwMTDigJMyMDI1KSIpDQoNCm10ZXh0KA0KICAiRmFsc2UtY29sb3IgUmVwcmVzZW50YXRpb25cbm9mIE1hY2F1IExhbmQgRXhwYW5zaW9uXG4yMDAwIOKAoiAyMDEwIOKAoiAyMDI1IiwNCiAgIHNpZGUgPSAxLCAgICAgICAjIHRvcA0KICAgbGluZSA9IDIsICAgICAjIG1vdmUgY2xvc2VyIHRvIHBsb3QgKC0gbW92ZXMgaW5zaWRlKQ0KICAgYWRqID0gMC42LA0KICAgY2V4ID0gMS41LA0KICBmb250ID0gMSwNCiAgIGNvbCA9ICJ3aGl0ZSIgKQ0KIA0KIA0KICMgQ2FwdGlvbg0KIG10ZXh0KA0KICAiQ3JlYXRlZCBieSBKaWF0b25nIFN1IiwNCiAgc2lkZSA9IDEsDQogIGxpbmUgPSA0LA0KICBhZGogPSAwLjYyLA0KICBjZXggPSAxLA0KICBjb2wgPSAiZ3JleSIpDQogDQpsZWdlbmQoDQogICB4ID0geF9sZWcsDQogICB5ID0geV9sZWcsDQogICBsZWdlbmQgPSBjKA0KICAgICAiQ2hhbmdlIGJldHdlZW4gMjAxMC0yMDI1IiwNCiAgICAgIkNoYW5nZSBiZXR3ZWVuIDIwMDAtMjAxMCIsDQogICAgICJMYW5kIGluIGFsbCAzIHBlcmlvZHMiDQogICAgICMiV2F0ZXIiDQogICApLA0KICAgZmlsbCA9IGMoDQogICAgIHJnYigxLDAsMCksICAgIyByZWQgZm9yIDIwMjUNCiAgICAgcmdiKDEsMSwwKSwgICAjIHllbGxvdyBmb3IgMjAwMC0yMDEwDQogICAgIHJnYigxLDEsMSkgICAjIHdoaXRlIGluIGFsbCBwZXJpb2QNCiAgICAjcmdiKDAsMCwwKSAgICAjIGJsYWNrIGlzIHdhdGVyIA0KICAgKSwNCiAgIGJvcmRlciA9IE5BLA0KICAgY2V4ID0gMC44NSwNCiAgIGJnID0gTkEsDQogICB0ZXh0LmNvbCA9ICJ3aGl0ZSIsDQogICBidHkgPSAibiIgICApDQoNCmBgYA0KDQojIEludGVyYWN0aXZlIG1hcCANCg0KYGBge3J9DQoNCiNvbmx5IG9uZSBjb2xvciByZXByZXNlbnQgbGFuZO+8jHdhdGVyIGlzIE5BDQpwYWxfbGFuZCA8LSBjb2xvckZhY3RvcigNCiAgcGFsZXR0ZSA9IGMoIm9yYW5nZSIpLCAgIA0KICBkb21haW4gID0gYygxKSwNCiAgbmEuY29sb3IgPSAidHJhbnNwYXJlbnQiDQopDQoNCg0KYGBgDQoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQp5ZWFycyA8LSBjKCIxOTkwIiwiMTk5NSIsIjIwMDAiLCIyMDA1IiwiMjAxMCIsIjIwMTUiLCIyMDIwIiwiMjAyNSIpDQpsYXllcl9uYW1lcyA8LSBuYW1lcyhsYW5kX3N0YWNrKSAgIyAibGFuZF8xOTkwIiAuLi4NCg0KbSA8LSBsZWFmbGV0KCkgfD4NCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgICMgYmFzZW1hcA0KDQojIGFkZCBsYW5kIG1hc2sgZm9yIGVhY2ggeWVhcg0KZm9yIChpIGluIHNlcV9hbG9uZyhsYXllcl9uYW1lcykpIHsNCiAgbSA8LSBtIHw+DQogICAgYWRkUmFzdGVySW1hZ2UoDQogICAgICBsYW5kX3N0YWNrW1tpXV0sDQogICAgICBjb2xvcnMgID0gcGFsX2xhbmQsDQogICAgICBvcGFjaXR5ID0gMC44LA0KICAgICAgcHJvamVjdCA9IFRSVUUsICAgICAgICAgICAgICAgICAgIyAgV0dTODQgLSBsZWFmbGV0DQogICAgICBncm91cCAgID0geWVhcnNbaV0NCiAgICApDQp9DQoNCiMgbGF5ZXIgY29udHJvbChjaG9zZSB5ZWFyKQ0KbSA8LSBtIHw+DQogIGFkZExheWVyc0NvbnRyb2woDQogICAgb3ZlcmxheUdyb3VwcyA9IHllYXJzLA0KICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkNCiAgKSB8Pg0KICBhZGRDb250cm9sKA0KICAgICJORFdJLWJhc2VkIExhbmQgTWFzayBmb3IgTWFjYXUgKDE5OTDigJMyMDI1KSIsDQogICAgcG9zaXRpb24gPSAiYm90dG9tbGVmdCINCiAgKQ0KDQptICANCg0KYGBgDQoNCmBgYHtyIHNhdmUgaHRtbCwgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoaHRtbHdpZGdldHMpDQoNCnNhdmVXaWRnZXQobSwgIm1hY2F1X3JlY2xhbWF0aW9uX2ludGVyYWN0aXZlLmh0bWwiLCBzZWxmY29udGFpbmVkID0gVFJVRSkNCg0KYGBgDQoNCg==